type StorageType = 'localStorage' | 'sessionStorage';

interface StorageData<T = unknown> {
  value: T;
  expire?: number;
}

interface CacheOptions {
  expire?: number; // 过期时间（毫秒）
  type?: StorageType; // 存储类型
}

/**
 * Storage 工具类
 */
export class Storage {
  private storage: globalThis.Storage;
  private prefix: string;

  constructor(type: StorageType = 'localStorage', prefix = 'app_') {
    this.storage = type === 'localStorage' ? window.localStorage : window.sessionStorage;
    this.prefix = prefix;
  }

  /**
   * 设置缓存
   * @param key 缓存键
   * @param value 缓存值
   * @param options 配置项
   */
  public set<T>(key: string, value: T, options: CacheOptions = {}): void {
    const { expire } = options;
    const data: StorageData<T> = {
      value,
      ...(expire ? { expire: Date.now() + expire } : {}),
    };

    try {
      this.storage.setItem(this.getKey(key), JSON.stringify(data));
    } catch (error) {
      // 处理存储已满等错误
      console.error('Storage set error:', error);
    }
  }

  /**
   * 获取缓存
   * @param key 缓存键
   * @param defaultValue 默认值
   */
  public get<T>(key: string, defaultValue?: T): T | undefined {
    const item = this.storage.getItem(this.getKey(key));

    if (!item) return defaultValue;

    try {
      const data: StorageData<T> = JSON.parse(item);

      // 判断是否过期
      if (data.expire && data.expire < Date.now()) {
        this.remove(key);
        return defaultValue;
      }

      return data.value;
    } catch (error) {
      return defaultValue;
    }
  }

  /**
   * 移除缓存
   * @param key 缓存键
   */
  public remove(key: string): void {
    this.storage.removeItem(this.getKey(key));
  }

  /**
   * 清空所有缓存
   */
  public clear(): void {
    this.storage.clear();
  }

  /**
   * 获取所有缓存键
   */
  public keys(): string[] {
    return Object.keys(this.storage)
      .filter((key) => key.startsWith(this.prefix))
      .map((key) => key.slice(this.prefix.length));
  }

  /**
   * 是否存在某个缓存
   * @param key 缓存键
   */
  public has(key: string): boolean {
    return this.get(key) !== undefined;
  }

  /**
   * 获取缓存数量
   */
  public count(): number {
    return this.keys().length;
  }

  /**
   * 获取完整键名
   * @param key 缓存键
   */
  private getKey(key: string): string {
    return `${this.prefix}${key}`;
  }
}

// 创建默认实例 localStorage
export const storage = new Storage();

// 创建会话存储实例 sessionStorage
export const sessionStorage = new Storage('sessionStorage');
